package elements;

import java.util.ArrayList;
import java.util.HashMap;
import shapes.*;

public class Window {

	double[][] matriz;
	public double x0 = 0, y0 = 0;
	// window height, window width
	private int wh, ww;

	private int cont = 0;

	double angulo = 0, cos = 1, sen = 0, zoom = 1, steps = 20;

	public HashMap<String, Shape> shapes;
	public HashMap<String, Shape> clipshapes;

	public Window(HashMap<String, Shape> s, HashMap<String, Shape> cs) {
		this.shapes = s;
		this.clipshapes = cs;
		matriz = new double[3][3];
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 3; j++)
				if (i == j)
					matriz[i][j] = 1;
				else
					matriz[i][j] = 0;
	}

	public void setViewportDimension(int w, int h) {
		wh = h;
		ww = w;
	}

	double[][] normPoints(double[][] p) {
		double[][] pts = new double[2][p[0].length];
		for (int i = 0; i < p[0].length; i++) {
			double[][] m = { { p[0][i], p[1][i], 1 } };
			m = multiplica(m, matriz);
			pts[0][i] = m[0][0] * (zoom / ww) - 50 / ww;
			pts[1][i] = m[0][1] * (zoom / wh) + 20 / wh;
		}
		return pts;
	}

	public void rotate(double ang) {
		this.angulo += ang;
		cos = Math.cos(Math.toRadians(ang));
		sen = Math.sin(Math.toRadians(ang));
		double[][] m = { { cos, sen, 0 }, { -sen, cos, 0 }, { 0, 0, 1 } };
		matriz = multiplica(matriz, m);
		refresh();
	}

	public void move(double dx, double dy) {
		x0 += dx / zoom;
		y0 += dy / zoom;
		double[][] m = { { 1, 0, 0 }, { 0, 1, 0 },
				{ -dx / zoom, -dy / zoom, 1 } };
		matriz = multiplica(matriz, m);
		refresh();
	}

	public double[][] multiplica(double[][] a, double[][] b) {
		double[][] c = new double[a.length][b[0].length];
		for (int i = 0; i < a.length; i++)
			for (int j = 0; j < b[0].length; j++)
				for (int k = 0; k < a[0].length; k++)
					c[i][j] += a[i][k] * b[k][j];
		return c;
	}

	public void zoomOut(double z) {
		double zm = z;
		if (zm >= 100)
			zm = 0.90;

		zoom *= (1 - zm / 100);
		steps = 20 * zoom;
		for (Shape obj : shapes.values())
			for (int i = 0; i < obj.ptsn[0].length; i++) {
				obj.ptsn[0][i] *= zoom;
				obj.ptsn[1][i] *= zoom;
			}
		refresh();
	}

	public void zoomIn(double z) {
		zoom *= (1 + z / 100);
		steps = 20 * zoom;
		for (Shape obj : shapes.values())
			for (int i = 0; i < obj.ptsn[0].length; i++) {
				obj.ptsn[0][i] *= zoom;
				obj.ptsn[1][i] *= zoom;
			}
		refresh();
	}

	public void refresh() {
		clipshapes = new HashMap<String, Shape>();

		for (Shape obj : shapes.values()) {
			obj.ptsn = normPoints(obj.pts);
			clip(obj);
		}
	}

	public void clip(Shape obj) {
		switch (obj.type) {
		case 0: // PONTO
			if (getRegionCodes(obj.ptsn[0][0], obj.ptsn[1][0]).equals("0000")) {
				clipshapes.put(obj.name, obj);
				return;
			}
			break;
		default:
			clipshapes.put(obj.name, obj);
			break;
		}

	}

	private void clipLinha(Shape obj){
		if(and(
				getRegionCodes(obj.ptsn[0][0],obj.ptsn[1][0])
				,getRegionCodes(obj.ptsn[1][0],obj.ptsn[1][1])
				) != 0){
			
		}
	}

	private int and(String a, String b) {
		return 0;
	}

	public String getRegionCodes(double px, double py) {
		double x = px;
		double y = py;
		System.out.println(py);

		int codX = 0;
		int codY = 0;
		// X
		if (x < -1) {
			codX = -1;
		} else if (x > 1) {
			codX = 1;
		}

		// Y
		if (y < -1) {
			codY = -1;
		} else if (y > 1) {
			codY = 1;
		}

		String cod = getRC(codX) + getRC(codY);
		return cod;
	}

	private String getRC(int v) {
		// 1 -> 10
		// -1-> 01
		// 0 -> 00

		switch (v) {
		case 1:
			return "10";
		case -1:
			return "01";
		case 0:
			return "00";
		}
		return "22";
	}

}
